#pragma once

#include<iostream>
#include<queue>
#include<pthread.h>
#include"Log.hpp"
#include"Task.hpp"

#define NUM 6


class ThreadPool
{
    private:
        int num;
        bool stop;
        std::queue<Task> task_queue;
        pthread_mutex_t lock;
        pthread_cond_t cond;

        ThreadPool(int _num=NUM)
            :num(_num),stop(false)
        {
            pthread_mutex_init(&lock,nullptr);
            pthread_cond_init(&cond,nullptr);
        }
        ThreadPool(const ThreadPool &)
        {}
        static ThreadPool* single_instance;
    public:
        static ThreadPool* getinstance()
        {
            static pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;
            if(single_instance==nullptr)
            {
                pthread_mutex_lock(&mymutex);
                if(single_instance==nullptr)
                {
                    single_instance=new ThreadPool();
                    single_instance->InitThreadPool();
                }
                pthread_mutex_unlock(&mymutex);
            }
            return single_instance;
        }
        bool IsStop() // 判断是否停止
        {
            return stop;
        }
        bool TaskQueueIsEmpty() // 任务队列是否为空
        {
            return task_queue.size()==0?true:false;
        }
        void Lock() // 对资源加锁
        {
            pthread_mutex_lock(&lock);
        }
        void UnLock() // 对资源解锁
        {
            pthread_mutex_unlock(&lock);
        }
        void ThreadWait() // 在特定条件下等待线程
        {
            pthread_cond_wait(&cond,&lock);
        }
        void ThreadWakeup() // 在特定条件下唤醒线程
        {
            pthread_cond_signal(&cond);
        }
        static void* ThreadRoutine(void* args) // 线程工作流程
        {
            ThreadPool *tp=(ThreadPool*)args;
            while(true)
            {
                Task t;
                tp->Lock();
                while(tp->TaskQueueIsEmpty())
                {  
                    tp->ThreadWait(); //当我醒来的时候，一定占有互斥锁
                }
                tp->PopTask(t);
                tp->UnLock();
                t.ProcessOn();

                
            }
            return nullptr;
        }
        bool InitThreadPool() // 初始化线程池
        {
            for(int i=0;i<NUM;i++)
            {
                pthread_t tid;
                if(pthread_create(&tid,nullptr,ThreadRoutine,this)!=0)
                {
                    LOG(FATAL,"create threadpool failed");
                    return false;
                }
            }
            LOG(INFO,"create threadpool success");
            return true;
        }

        void PushTask(const Task &task) // 进队列
        {
            Lock();
            task_queue.push(task);
            UnLock();
            ThreadWakeup();
        }

        void PopTask(Task &task) // 出队列
        {
            task=task_queue.front();
            task_queue.pop();
        }

        ~ThreadPool() 
        {
            pthread_mutex_destroy(&lock);
            pthread_cond_destroy(&cond);
        }
};
ThreadPool* ThreadPool::single_instance=nullptr;